<?php

/**
 * CelebrioMail Default
 *
 * @copyright  Copyright (c) 2011 Celebrio Software
 * @package    CelebrioMail
 */

namespace ApplicationsModule\MailModule;

use WebtopModule\BasePresenter;
use ApplicationsModule\PeopleModule\PeopleManagement;
use Nette\Environment;
use Nette\Forms\Form;
use Nette\Application\AppForm;

use Nette\VisualPaginator;

class DefaultPresenter extends BasePresenter {

    private static $ITEMS_PER_PAGE = 5;

    /** @var MailManagment */
    private $mailManager;

    /** @var array of MailServer */
    private $activeMailServers = array();

    /**
     * Lazy getter for MailManagment
     * @return MailManagment
     */
    private function getMailManager() {
        if ($this->mailManager === NULL) {
            $this->mailManager = new MailManagement();
        }
        return $this->mailManager;
    }

    public function startup() {
        parent::startup();
        header("Content-type:text/html; charset=utf-8"); // TODO: poresit - moving to the applications module will fix this
        if ($this->isAjax()) {
            $this->invalidateControl("celebriomailappSnippet");
        }

        if (!Environment::getUser()->isLoggedIn()) {
            throw new \Exception("User is not authenticated");
            return;
        }

        $this->activeMailServers = $this->getMailManager()->getMailServers(Environment::getUser()->getIdentity()->id);

        if (!isset($this->activeMailServers[0])) {
            $this->forward("Settings:settings"); // if no mail server is set up, you got to do that first
        }

        $this->template->activeLink = "inbox";
    }

    private function readMails($folder = "INBOX") {
        // TODO: mail headers should be stored in database...
        $this->template->headers = array();
        $mailReceiver = new MailReceiver($this->activeMailServers[0]);
        if (!$mailReceiver->connect($folder)) {
            return;
        }
        $headers = array();

        $mailsTotal = $mailReceiver->getTotalMails(); //total number of mails

        //inicialize paginator and variables
        $paginator = $this["paginator"]->getPaginator(); //get component paginator
        $paginator->itemCount = $mailsTotal; //total number of items (mails)

        $mailsLimit = $paginator->itemsPerPage; //limit of mails per one page
        $pagOffset = $paginator->offset; //offset in paginator

        //calculation of start and end numbers to read headers, cause of backward loading of emails
        $endReadNum = $mailsTotal - $pagOffset;
        $startReadNum = $endReadNum - $mailsLimit + 1;
        if ($startReadNum < 1) {
            $startReadNum = 1;
        }

        $originalHeaders = $mailReceiver->getHeaders($startReadNum, $endReadNum);
        $headers = $this->canonizeHeaders($originalHeaders, $mailReceiver, $folder);

        $this->template->totalMails = $mailsTotal;
        $this->template->headers = array_reverse($headers);

        $mailReceiver->close();
    }

    private function canonizeHeaders($originalHeaders, $mailReceiver, $folder) {
        $headers = array();
        if (is_array($originalHeaders)) {
            foreach ($originalHeaders as $header) {
                $number = $header->msgno;
                $from = $mailReceiver->decodeMimeString($header->from);
                if (\strpos($from, "<") > 1) $from_reduced = trim(substr($from, 0, \strpos($from, "<")));
                else $from_reduced = $from;
                $subject = $mailReceiver->decodeMimeString($header->subject);
                if (strlen($subject) > 20) $subject = \substr($subject, 0, 25) . "...";
                $time = strtotime($header->date);
                $unread = ($header->seen) ? FALSE : TRUE; // TODO: test
                if (date("dmY") == date("dmY", $time)) $date = date("H:i", $time);
                else $date = date("M d", $time);
                $headers[] = array("number" => $number, "from" => $from, "from_reduced" => $from_reduced, "subject" => $subject, "date" => $date, "unread" => $unread, "folder" => $folder);
            }
        }
        return $headers;
    }

    public function createComponentPaginator() {
        $visualPaginator = new VisualPaginator();
        $visualPaginator->paginator->setItemsPerPage(self::$ITEMS_PER_PAGE);
        return $visualPaginator;
    }

    public function renderDefault() {
        $this->template->activeLink = "inbox";
        $this->readMails();
    }

    public function renderCompose() {
        $this->template->activeLink = "compose";
        $this->template->composeForm = $this["composeForm"];
        
        $peopleManager = new PeopleManagement();
        $this->template->people = $peopleManager->getFriends();
    }

    public function createComponentComposeForm() {
        $form = new AppForm();
        $form->addHidden("to", "")->htmlId = "compose-to";
        $form->addTextArea("contents", _("Text:"))
                ->addRule(Form::FILLED, _('Please write your message.'));

        $form->addSubmit('submited', _('Send'))->htmlId = "submit-compose";
        $form->onSubmit[] = callback($this, 'composeSubmitted');
        
        return $form;
    }

    /**
     * process submitted settings
     * @param Form
     */
    public function composeSubmitted($form) {
        $values = $form->values;
        $this->sendMail($values);
    }

    /**
     * sends an e-mail
     * @param array $values
     * @return Mixed returns boolean or an array of undelivered e-mails
     */
    private function sendMail($values) {
        // TODO: add support for other mail accounts
        $mailer = new MailSender($this->activeMailServers[0]);
        if (!$mailer->connect()) {
            $this->template->composeStatus = _("Celebrio can not connect to SMTP server.");
            return FALSE;
        }
        $result = $mailer->sendMail($values);
        if (is_array($result)) {
            $this->template->composeStatus = _("E-mail could not be delivered to one or more recipients:");
            foreach ($result as $mail) {
                $this->template->composeStatus += " $mail,";
            }
            $this->template->composeStatus = substr($this->template->composeStatus, -1);
        } elseif ($result == TRUE) {
            $this->template->composeStatus = _("E-mail sent.");
        } else {
            $this->template->composeStatus = _("An error occurred and your e-mail could not be delivered.");
        }
    }

    public function renderSent() {
        $this->template->activeLink = "sent";
        $sent = $this->activeMailServers[0]->getSentFolder();
        if (empty($sent)) return;
        $this->readMails($this->activeMailServers[0]->getSentFolder());
    }

// TODO: remove drafts
    public function renderDrafts() {
        $this->template->activeLink = "drafts";
        $sent = $this->activeMailServers[0]->getDraftsFolder();
        if (empty($sent)) return;
        $this->readMails($this->activeMailServers[0]->getDraftsFolder());
    }

    public function renderMailbody() {
        if (!isset($_GET["number"]) || (int)$_GET["number"] == 0) return;
        $mailReceiver = new MailReceiver($this->activeMailServers[0]);
        $folder = $_GET["folder"];
        if ($folder != $this->activeMailServers[0]->getSentFolder() &&
            $folder != $this->activeMailServers[0]->getDraftsFolder() &&
            $folder != $this->activeMailServers[0]->getTrashFolder() &&
            $folder != $this->activeMailServers[0]->getSpamFolder()
        ) {

            $folder = "INBOX";
        }
        if (!$mailReceiver->connect($folder)) {
            return;
        }
        // TODO: opravit kodovani a nl2br
        //header ( "Content-type:text/html; charset=utf-8" );
        $mail_id = (int)$_GET["number"];
        $this->template->mailContents = $mailReceiver->getBody($mail_id);
        $attach = $mailReceiver->getMailAttachments($mail_id);
        if (!empty($attach))
            $this->template->attachments = $attach;
        $mailReceiver->close();
    }

    public function renderMail() {
        $folder = $_GET["folder"];
        if ($folder == $this->activeMailServers[0]->getSentFolder()) $this->template->activeLink = "sent";
        elseif ($folder == $this->activeMailServers[0]->getDraftsFolder()) $this->template->activeLink = "drafts";
        elseif ($folder == $this->activeMailServers[0]->getTrashFolder()) $this->template->activeLink = "trash";
        elseif ($folder == $this->activeMailServers[0]->getSpamFolder()) $this->template->activeLink = "spam";
        else {
            $this->template->activeLink = "inbox";
            $folder = "INBOX";
        }
        $this->template->mailFrom = "";
        $this->template->mailSubject = "";
        $this->template->mailTo = "";
        $this->template->mailBody = "";
        if (!isset($_GET["number"]) || (int)$_GET["number"] == 0) return;
        $mailReceiver = new MailReceiver($this->activeMailServers[0]);
        $this->template->mailFolder = $folder;
        if (!$mailReceiver->connect($folder)) {
            return;
        }
        $header = $mailReceiver->getHeader((int)$_GET["number"]);
        if (is_object($header)) {
            $this->template->mailFrom = ((isset($header->from[0]->personal))
                    ? "\"" . $mailReceiver->decodeMimeString($header->from[0]->personal) . "\" "
                    : "") . "<" . $header->from[0]->mailbox . "@" . $header->from[0]->host . "> ";
            $this->template->mailSubject = $mailReceiver->decodeMimeString($header->subject);
            $this->template->mailTo = "";
            if (isset($header->to) && is_array($header->to)) {
                foreach ($header->to as $to) {
                    $this->template->mailTo .= ((isset($to->personal))
                            ? "\"" . $mailReceiver->decodeMimeString($to->personal) . "\" "
                            : "") . "<" . $to->mailbox . "@" . $to->host . ">, ";
                }
                $this->template->mailTo = substr($this->template->mailTo, 0, strlen($this->template->mailTo) - 2);
            }
            //$this->template->mailBody = $mailReceiver->getBody((int)$_GET["number"]);
            $this->template->mailNumber = (int)$_GET["number"];
        }
        $mailReceiver->close();
    }

}